import 'package:flutter/material.dart';

/// Created by XieXin on 2020/11/14
/// 自定义下划线
class XUnderlineTabIndicator extends Decoration {
  /// Create an underline style selected tab indicator.
  ///
  /// The [borderSide] and [insets] arguments must not be null.
  const XUnderlineTabIndicator({
    this.borderSide = const BorderSide(width: 2.0, color: Colors.white),
    this.insets = EdgeInsets.zero,
    this.isRound = false,
    this.width,
  })  : assert(insets != null);

  /// The color and weight of the horizontal line drawn below the selected tab.
  final BorderSide borderSide;

  /// Locates the selected tab's underline relative to the tab's boundary.
  ///
  /// The [TabBar.indicatorSize] property can be used to define the
  /// tab indicator's bounds in terms of its (centered) tab widget with
  /// [TabIndicatorSize.label], or the entire tab with [TabIndicatorSize.tab].
  final EdgeInsetsGeometry? insets;

  ///是否圆角
  final bool isRound;

  ///宽度
  final double? width;

  @override
  Decoration? lerpFrom(Decoration? a, double t) {
    if (a is XUnderlineTabIndicator) {
      return XUnderlineTabIndicator(
        borderSide: BorderSide.lerp(a.borderSide, borderSide, t),
        insets: EdgeInsetsGeometry.lerp(a.insets, insets, t),
      );
    }
    return super.lerpFrom(a, t);
  }

  @override
  Decoration? lerpTo(Decoration? b, double t) {
    if (b is XUnderlineTabIndicator) {
      return XUnderlineTabIndicator(
        borderSide: BorderSide.lerp(borderSide, b.borderSide, t),
        insets: EdgeInsetsGeometry.lerp(insets, b.insets, t),
      );
    }
    return super.lerpTo(b, t);
  }

  @override
  XUnderlinePainter createBoxPainter([VoidCallback? onChanged]) {
    return XUnderlinePainter(this, onChanged, isRound, width);
  }
}

class XUnderlinePainter extends BoxPainter {
  XUnderlinePainter(
      this.decoration, VoidCallback? onChanged, this.isRound, this.width)
      : super(onChanged);
  final bool isRound;
  final double? width;

  final XUnderlineTabIndicator decoration;

  BorderSide get borderSide => decoration.borderSide;

  EdgeInsetsGeometry? get insets => decoration.insets;

  Rect _indicatorRectFor(Rect rect, TextDirection textDirection) {
    final Rect indicator = insets!.resolve(textDirection).deflateRect(rect);
    //取中间坐标
    double cw = (indicator.left + indicator.right) / 2;
    if (width == null) {
      return Rect.fromLTWH(indicator.left, indicator.bottom - borderSide.width,
          indicator.width, borderSide.width);
    } else {
      return Rect.fromLTWH(cw - width! / 2, indicator.bottom - borderSide.width,
          width!, borderSide.width);
    }
  }

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    final Rect rect = offset & configuration.size!;
    final TextDirection textDirection = configuration.textDirection!;
    final Rect indicator =
        _indicatorRectFor(rect, textDirection).deflate(borderSide.width / 2.0);
    StrokeCap strokeCap;
    if (isRound) {
      strokeCap = StrokeCap.round;
    } else {
      strokeCap = StrokeCap.square;
    }
    final Paint paint = borderSide.toPaint()..strokeCap = strokeCap;
    canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint);
  }
}
